﻿using HCMS.Entities.OAuth2;
using HCMS.Extensions;
using HCMS.IServices.OAuth2;
using HCMS.Utils;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;

namespace HCMS.HttpApi.Site.Filter
{
    /// <summary>
    /// Api 请求跟踪【开始】
    /// </summary>
    /// <remarks>
    /// 方法 执行 过滤器
    /// </remarks>
    public class ActionExecutionLogsFilter : Attribute, IAsyncActionFilter
    {
        /// <summary>
        /// 方法 执行时 调用
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            try
            {
                //--- Action 执行前
                var startTime = DateTime.Now;

                ControllerActionDescriptor? descriptor = context.ActionDescriptor as ControllerActionDescriptor;
                string currentControllerName = (descriptor?.ControllerName) ?? "";
                string currentActionName = (descriptor?.ActionName) ?? "";

                string httpMethod = context.HttpContext.Request.Method;
                string refererUrl = context.HttpContext.Request.GetReferer();
                string url = context.HttpContext.Request.GetCurrentUrl();
                string ip = context.HttpContext.Request.GetClientIp();
                var headerInfo = context.HttpContext.Request.GetHeaderInfo();
                var parameter = await context.HttpContext.Request.GetParameter();

                //--- 记录请求日志【开始】
                var logs = new ApiRequestLogs()
                {
                    ControllerName = currentControllerName,
                    ActionName = currentActionName,
                    HttpMethod = httpMethod,
                    RefererUrl = refererUrl,
                    Url = url,
                    Ip = ip,
                    HeaderInfo = string.Join("<br />", headerInfo),
                    Parameter = parameter,
                    StartTime = startTime
                };
                var serializeValule = JsonConvert.SerializeObject(logs);
                context.HttpContext.Items["apiRequestLogs"] = serializeValule;
            }
            catch (Exception ex)
            { }

            await next();

            //--- Action 执行后

        }
    }

    /// <summary>
    /// Api 请求跟踪【结束】
    /// </summary>
    /// <remarks>
    /// 方法正常执行并返回：系统在这里记录 请求日志；
    /// 方法抛出友好异常：系统在【全局异常 过滤器】记录 请求日志
    /// 
    /// 结果 执行 过滤器
    /// </remarks>
    public class ResultExecutionLogsFilter : IAsyncResultFilter
    {
        private readonly IApiRequestLogsAppService apiRequestLogsAppService;

        public ResultExecutionLogsFilter(IApiRequestLogsAppService apiRequestLogsAppService)
        {
            this.apiRequestLogsAppService = apiRequestLogsAppService;
        }

        /// <summary>
        /// 结果 执行时 调用
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
        {
            // 结果 执行前

            await next();

            // 结果 执行后

            try
            {
                //--- 记录请求日志【结束】
                var logs = context.HttpContext.Items["apiRequestLogs"].ToString("");
                if (!string.IsNullOrWhiteSpace(logs))
                {
                    var apiRequestLogs = JsonConvert.DeserializeObject<ApiRequestLogs>(logs) ?? new ApiRequestLogs();
                    var statusCode = context.HttpContext.Response.StatusCode;

                    if (statusCode == StatusCodes.Status200OK)
                    {
                        if (context.Result is OkObjectResult okResult)
                        {
                            var resultList = new List<string> 
                            {
                                "返回类型：OkObjectResult"
                            };
                            if (okResult.Value != null)
                            {
                                resultList.Add(string.Format("返回值：{0}", JsonConvert.SerializeObject(okResult.Value).Replace(",", ",<br />")));
                            }

                            apiRequestLogs.ResultInfo = string.Join("<br /><br />", resultList);
                        }
                        else
                        {
                            apiRequestLogs.ResultInfo = "返回其它类型结果";
                        }
                    }
                    else
                    {
                        apiRequestLogs.ResultInfo = $"请求失败。状态码：{statusCode}";
                    }

                    apiRequestLogs.EndTime = DateTime.Now;
                    var differenTime = DateTimeUtil.DifferenTimespan(apiRequestLogs.StartTime, apiRequestLogs.EndTime);
                    apiRequestLogs.ExecutionTime = differenTime.Milliseconds;

                    await apiRequestLogsAppService.BaseInsertAsync(apiRequestLogs);
                }
            }
            catch (Exception)
            {
            }
        }
    }
}
